﻿//
// Copyright (C) Ashish Kaila 2011
//

using System.Collections;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;

namespace Flipbook.Behaviors
{
    /// <summary>
    /// Reorders items within an list box
    /// </summary>
    public class ListBoxItemReorderingBehavior : Behavior<ListBox>
    {
        /// <summary>
        /// Called after the behavior is attached to an AssociatedObject.
        /// </summary>
        protected override void OnAttached()
        {
            base.OnAttached();

            Style itemContainerStyle = new Style(typeof(ListBoxItem));
            itemContainerStyle.Setters.Add(new Setter(ListBoxItem.AllowDropProperty, true));
            itemContainerStyle.Setters.Add(new EventSetter(ListBoxItem.PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(PreviewMouseLeftButtonDown)));
            itemContainerStyle.Setters.Add(new EventSetter(ListBoxItem.DropEvent, new DragEventHandler(ListBoxItemDrop)));
            AssociatedObject.ItemContainerStyle = itemContainerStyle;            
        }

        /// <summary>
        /// Previews the mouse left button down.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
        private void PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (!(sender is ListBoxItem))
            {                
                return;
            }

            _draggedItem = sender as ListBoxItem;
            DragDrop.DoDragDrop(_draggedItem, _draggedItem.DataContext, DragDropEffects.Move);
            _draggedItem.IsSelected = true;
        }

        /// <summary>
        /// Drops the list box item
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.DragEventArgs"/> instance containing the event data.</param>
        private void ListBoxItemDrop(object sender, DragEventArgs e)
        {
            if (!(sender is ListBoxItem))
            {
                return;
            }

            object draggedData = _draggedItem.DataContext;

            if (draggedData == null)
            {
                return;
            }

            object droppedOnData = (sender as ListBoxItem).DataContext;

            IList itemsCollection = AssociatedObject.ItemsSource as IList;

            if (itemsCollection == null)
            {
                return;               
            }

            int removedIndex = itemsCollection.IndexOf(draggedData);
            int droppedIndex = itemsCollection.IndexOf(droppedOnData);
            
            if (removedIndex < droppedIndex)
            {
                itemsCollection.Insert(droppedIndex + 1, draggedData);
                itemsCollection.RemoveAt(removedIndex);
            }
            else if (removedIndex != droppedIndex)
            {
                if (itemsCollection.Count > removedIndex)
                {
                    itemsCollection.Insert(droppedIndex, draggedData);
                    itemsCollection.RemoveAt(removedIndex + 1);
                }
            }

            AssociatedObject.SelectedIndex = droppedIndex;
        }

        // Private members
        private ListBoxItem _draggedItem;
    }
}
